<?php
/*
 *  Mcrypt 实践
 *  2016年10月27日 星期四
*/
namespace hyang\util;
use hyang\util\fs;
class Crypt{
    private static $ori_key;
    private static $_key;
    private static $_mode;
    private static $_iv;
    private static $cipher;// 密文
    public static $algoList;// 加密算法列表
    private static $algoType;// 当前的加密算法
    
    public function __construct($key=null)
    {
        //self::start($key);
        //$this->start($key);// 非静态可使用
        if($key) self::$cipher = $key;
        self::$algoList = mcrypt_list_algorithms("/usr/local/lib/libmcrypt");
    }
    // 加密参数设置- key/type
    public static function config($option)
    {
        if(!is_array($option)) return;
        if(isset($option['key'])) self::$_key = $option['key'];
        if(isset($option['type']) && in_array($option['type'],self::$algoList)) self::$algoType = $option['type'];        
    }
    public static function setKey($key)
    {
        if(is_file($key)) self::$ori_key = file_get_contents($key);
        elseif(is_string($key)) self::$ori_key = $key;
        elseif(is_callable($key)){
            $ctt = $key();
            if(is_string($ct)) self::$ori_key = $ctt;
        }
    }
    public static function getKey()
    {
        //return self::$ori_key;
        //echo '<br>'.self::$ori_key.' <br>'.self::$_key;
        return self::$_key;
    }
    public static function getCipher($fname=null)
    {
        $ctt = self::$cipher;
        if(empty($ctt)) return;
        if(is_string($fname) && $fname) return file_put_contents($fname,$ctt);
        return $ctt;
    }
    public static function start($key=null)
    {
        if(empty(self::$ori_key)){
            $key = $key? $key:uniqid();
            self::$ori_key = $key; 
        }
        else $key = self::$ori_key;
        /* 打开加密模块，并且创建初始向量 */
        /*
            MCRYPT_MODE_modename 常量中的一个，或以下字符串中的一个："ecb"，"cbc"，"cfb"，"ofb"，"nofb" 和 "stream"。
            wake? 报错
        */
        $type = self::$algoType? self::$algoType:'rc2';
        self::$_mode = mcrypt_module_open($type, '', 'ecb', '');// 可选加密方式- des/rc2/blowfish/cast_128/gost
        self::$_key = substr($key, 0, mcrypt_enc_get_key_size(self::$_mode));(new fs(APP_ROOT.Debug_Dir.'mcrypt.txt'))->append("\r\n".$type.'('.mcrypt_enc_get_key_size(self::$_mode).')');
        $iv_size = mcrypt_enc_get_iv_size(self::$_mode);
        self::$_iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    }
    public static function encode($data,$fname=null)
    {
        if(@is_file($data)) $data = file_get_contents($data);
        mcrypt_generic_init(self::$_mode, self::$_key, self::$_iv);
        $ctt = mcrypt_generic(self::$_mode,trim($data));
        self::$cipher = $ctt;
        return self::getCipher($fname);
    }
    // $data 数据可以是文件总获取[string/file]
    public static function decode($data)
    {
        if(@is_file($data)) $data = file_get_contents($data);
        mcrypt_generic_init(self::$_mode, self::$_key, self::$_iv);
        $ctt = mdecrypt_generic(self::$_mode, trim($data));            
        return $ctt;
    }
    public static function end()
    {
        /* 执行清理工作 */
        mcrypt_generic_deinit(self::$_mode);
        mcrypt_module_close(self::$_mode);
    }
}